#include "Key.h"

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Key
 *      Method:  Key
 * Description:  Contrói uma chave aleatória, mas passando a quantidade de bits
 *--------------------------------------------------------------------------------------
 */
Key::Key(int quality)
{
    // Atribui a quantidade de bits utilizado na esteganografia a partir da qualidade
    switch(quality)
    {
        // Qualidade baixa (4 bits)
        case LOW_QUALITY:
            nbits = 4;
            break;

        // Qualidade alta (1 bit)
        case HIGH_QUALITY:
            nbits = 1;
            break;

        // Qualidade média (2 bits)
        default:
            nbits = 2;
            break;
    }

    srand(time(NULL));

    // Inicializa o vetor de posições
    for(uint i = 0; i < KEY_SIZE; i++)
        position[i] = i;

    // Reordena aleatoriamente o vetor
    for(uint i = 0; i < KEY_SIZE; i++)
    {
        uint j = rand() % KEY_SIZE;
        uint aux = position[i];
        position[i] = position[j];
        position[j] = aux;
    }
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Key
 *      Method:  Key
 * Description:  Contrói uma chave a partir de um arquivo
 *--------------------------------------------------------------------------------------
 */
Key::Key(const string &key)
    : position{0}
{
    char name[KEY_SIZE + 1];;

    ifstream in(key);

    // Lê a chave do arquivo
    in.read(name, KEY_SIZE + 1);

    // Caso o tamanho do arquivo seja inválido
    if(in.gcount() != KEY_SIZE + 1)
        throw InvalidKeyException(key);

    // Atribui o vetor de novas posições a partir da representação da chave
    for(uint i = 0; i < KEY_SIZE; i++)
    {
        int index = name[i] - 'a';

        // Verifica se o índice é válido
        if(index < 0 || index >= KEY_SIZE || position[index] != 0)
            throw InvalidKeyException(key);

        position[index] = i;
    }

    // Atribui a quantidade de bits
    nbits = name[KEY_SIZE] - '0';
    if(nbits != 1 && nbits != 2 && nbits != 4)
        throw InvalidKeyException(key);

    in.close();
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  Key
 *      Method:  write
 * Description:  Escreve a chave em um arquivo
 *--------------------------------------------------------------------------------------
 */
void Key::write(const string &key)
{
    char name[KEY_SIZE + 1];

    // Transforma o vetor de posições em uma representação gráfica
    for(uint i = 0; i < KEY_SIZE; i++)
        name[position[i]] = 'a' + i;

    // Quantidade de bits
    name[KEY_SIZE] = (char) (nbits + '0');

    ofstream out(key);

    // Escreve a representação das posições no arquivo
    out.write(name, KEY_SIZE + 1);
    out.close();

}
